package com.gabejeff.engine;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.util.HashMap;
import java.util.Stack;

public class ConceptualMenu {
	
	private final int MENU_ITEM_SIZE = 36;
	private final int MENU_HEADER_SIZE = 64;
	
	private final Color SELECTED_COLOR = Color.BLUE;
	private final Color DEFAULT_COLOR = Color.WHITE;
	
	private Font headerFont = null;
	private Font menuFont = null;
	
	private int selectedItem = 0;
	private int currentMenu = 0;
	
	private String[] topLevel;
	private HashMap<Integer, String[]> subMenus;
	private HashMap<Integer, MenuAction> actions;
	private Stack<Integer> history;
	
	public ConceptualMenu(String[] topLevel) 
	{
		this.topLevel = topLevel;
		subMenus = new HashMap<Integer, String[]>();
		actions = new HashMap<Integer, MenuAction>();
		history = new Stack<Integer>();
	}
	
	public void addSubMenu(int trigger, String[] menuItems) 
	{
		if (trigger > 0 && trigger < topLevel.length) {
			subMenus.put(trigger, menuItems);
		}
	}
	
	public void removeSubMenu(int trigger) 
	{
		if (subMenus.containsKey(trigger)) {
			subMenus.remove(trigger);
		}
	}
	
	public void moveDown() 
	{
		if ( (currentMenu == 0 && selectedItem < topLevel.length - 1) ||
			 (currentMenu > 0 && selectedItem < subMenus.get(currentMenu).length - 1) ) {
			
			selectedItem++;
			
		}
	}
	
	public void moveUp() 
	{
		if ( selectedItem > 1 ) {
			
			selectedItem--;
			
		}
	}
	
	public void performAction() 
	{
		/*
		 * If there is a submenu associated with this item
		 */
		if (subMenus.containsKey(selectedItem)) {
			
			history.push(currentMenu);
			currentMenu = selectedItem;
			selectedItem = 0;
			
		} else {
			
			/*
			 * If not, let's check if there is an action associated with this item and then
			 * perform that action.
			 */
			int hash = getHashedValue(currentMenu, selectedItem);
			if (actions.containsKey(hash)) {
				actions.get(hash).performAction();
			}
			
		}
	}
	
	private int getHashedValue(int x, int y) {
		
		String s = "" + x + y;
		return s.hashCode();
		
	}
	
	public void addAction(int trigger, int item, MenuAction a) {
		
		actions.put(getHashedValue(trigger, item), a);
		
	}
	
	public void removeActionListener(int trigger, int item) {
		
		int hash = getHashedValue(trigger, item);
		if (actions.containsKey(hash)) {
			
			actions.remove(hash);
			
		}
		
	}
	
	public void goBack() {
		if (history.size() > 0) {
			
			currentMenu = history.pop();
			selectedItem = 0;
			
		}
	}
	
	public void draw(Graphics2D g2d, Dimension dim) 
	{
		g2d.setColor(Color.WHITE);
		
		if (headerFont == null) {
			headerFont = new Font(g2d.getFont().getName(), g2d.getFont().getStyle(), MENU_HEADER_SIZE);
		}
		g2d.setFont(headerFont);
		
		String header;
		int numItems;
		if (currentMenu == 0) {
			header = topLevel[0];
			numItems = topLevel.length;
		} else {
			header = subMenus.get(currentMenu)[0];
			numItems = subMenus.get(currentMenu).length;
		}
		
		g2d.drawString(header, (int)(dim.getWidth()/2 - g2d.getFontMetrics().stringWidth(header)/2), 100);
		
		int offset = g2d.getFontMetrics().getHeight() + 25;

		if (menuFont == null) {
			menuFont = new Font(g2d.getFont().getName(), g2d.getFont().getStyle(), MENU_ITEM_SIZE);
		}
		
		String item;
		for (int i=1;i<numItems;i++) {
			if (currentMenu == 0) {
				item = topLevel[i];
			} else {
				item = subMenus.get(currentMenu)[i];
			}
			if (selectedItem == i) {
				g2d.setColor(SELECTED_COLOR);
				g2d.setFont(menuFont.deriveFont(menuFont.getStyle() | Font.ITALIC));
			} else {
				g2d.setColor(DEFAULT_COLOR);
				g2d.setFont(menuFont);
			}
			g2d.drawString(item, (int)(dim.getWidth()/2 - g2d.getFontMetrics().stringWidth(item)/2), 100 + offset);
			offset+=g2d.getFontMetrics().getHeight() + 25;
		}
	}
	
	public boolean isTopLevel() {
		return (currentMenu == 0);
	}
	
	public void reset() {
		this.currentMenu = 0;
		this.selectedItem = 0;
	}

}
